#include <QMouseEvent>

#include "minesweeprwidget.h"
#include "global_config.h"

#include "QDebug"

#include "network_message.h"
#include "left_button_clicked.pb.h"
#include "tcp_client.h"

MineSweeprWidget::MineSweeprWidget(QWidget *parent) :
    QWidget{parent},
    grids_(gMineSweeperRowNum, QVector<std::shared_ptr<Cell>>(gMineSweeperColNum))
{
    int width = gMineSweeperCellPixSize * gMineSweeperColNum;
    int height = gMineSweeperCellPixSize * gMineSweeperRowNum;

    setFixedSize(width, height);
    for (int i = 0; i < rowNum(); i++) {
        for (int j = 0; j < colNum(); j++) {
            grids_[i][j] = std::make_shared<Cell>(this);
            grids_[i][j]->move(gMineSweeperCellPixSize * j, gMineSweeperCellPixSize * i);
            grids_[i][j]->showImage();
        }
    }
}

void MineSweeprWidget::calculateBombsAround()
{
    for (int i = 0; i < rowNum(); i++) {
        for (int j = 0; j < colNum(); j++) {
            Position pos(i, j);
            auto cell = cellAtPos(pos);
            int bombsAround = 0;
            for (int k = -1; k <= 1; k++) {
                for (int l = -1; l <= 1; l++) {
                    if (k == 0 && l == 0) {
                        continue;
                    }

                    Position curPos(i + k, j + l);
                    if (!isPositionValid(curPos)) {
                        continue;
                    }

                    auto curCell = cellAtPos(curPos);
                    if (curCell->isBomb()) {
                        bombsAround++;
                    }
                }
            }
            cell->setBombsAround(bombsAround);
        }
    }
}

/* 初始化游戏时服务器会告诉客户端哪些位置是地雷，同时服务器会预先开辟一处没有地雷的区域，双方玩家在此基础上开始对局 */
void MineSweeprWidget::onInitGame(uint8_t playerIndex, const QVector<Position> &bombsPosition,
                                  const QVector<Position> &positionsOpenedByServer)
{
    for (const auto &pos : bombsPosition) {
        auto cell = cellAtPos(pos);
        if (cell != nullptr) {
            cell->setIsBomb(true);
        }
    }

    calculateBombsAround();

    for (const auto &pos : positionsOpenedByServer) {
        auto cell = cellAtPos(pos);
        if (cell != nullptr) {
            cell->setIsOpened(true);
            cell->setOpenedByWho(Cell::SYSTEM);
            cell->showImage();
        }
    }
    isGameInited_ = true;
}

void MineSweeprWidget::onLocalLeftButtonClicked(const Position &pos)
{
    auto cell = cellAtPos(pos);
    if (cell == nullptr || cell->isOpened() || cell->state() == Cell::FLAGED) {
        return;
    }

    LeftButtonClickedC2SProto leftButtonClickedProto;
    auto posPtr = leftButtonClickedProto.mutable_pos();
    posPtr->set_row(pos.row_);
    posPtr->set_col(pos.col_);

    leftButtonClickedProto.set_player_index(static_cast<::LeftButtonClickedC2SProto_PlayerIndex>(playerIndex_));

    network_message msg(MSG_TYPE_C2S_LEFT_BUTTON_CLICKED, leftButtonClickedProto.SerializeAsString());
    auto msgStr = msg.to_string();

    if (clientPtr_ == nullptr) {
        return;
    }

    clientPtr_->send_message(msgStr);
}

void MineSweeprWidget::onLocalRightButtonClicked(const Position &pos)
{
    auto cell = cellAtPos(pos);
    if (cell == nullptr || cell->isOpened()) {
        return;
    }

    if (cell->state() == Cell::ORIGINAL) {
        cell->setState(Cell::FLAGED);
    } else if (cell->state() == Cell::FLAGED) {
        cell->setState(Cell::QUESTIONED);
    } else {
        cell->setState(Cell::ORIGINAL);
    }

    cell->showImage();
}

void MineSweeprWidget::onLocalLeftRightButtonClicked(const Position &pos)
{
    auto cell = cellAtPos(pos);
    if (cell == nullptr || !cell->isOpened()) {
        return;
    }

    auto bombsAround = cell->bombsAround();

    auto flagAround = 0;
    /* 遍历周围至多8个方格，统计被标记为Flagged的方格数量 */
    for (int i = -1; i <= 1; i++) {
        for (int j = -1; j <= 1; j++) {
            Position curPos(pos.row_ + i, pos.col_ + j);
            if (!isPositionValid(curPos)) {
                continue;
            }

            auto curCell = cellAtPos(curPos);
            if (curCell->state() == Cell::FLAGED) {
                flagAround++;
            }
        }
    }

    /* 只有周围的地雷个数等于旗帜个数时才打开其他未被标记、或者标记为疑问的方格 */
    if (flagAround != bombsAround) {
        return;
    }

    /* 遍历周围至多8个未被打开的方格，当方格已被打开或者被标记为Flaged，就打开它 */
    for (int i = -1; i <= 1; i++) {
        for (int j = -1; j <= 1; j++) {
            Position curPos(pos.row_ + i, pos.col_ + j);
            if (!cell->isOpened() || cell->state() == Cell::FLAGED) {
                continue;
            }

            onLocalLeftButtonClicked(curPos);
        }
    }

}

void MineSweeprWidget::onRemoteLeftButtonClicked(bool isOpponent, const QVector<Position> &positions)
{
    for (const auto &pos : positions) {
        auto cell = cellAtPos(pos);
        cell->setIsOpened(true);
        cell->setOpenedByWho(isOpponent ? Cell::OPPONENT : Cell::ME);
        cell->showImage();
    }

    if (isOpponent) {
        auto &opponentPlayer = getOpponentPlayer();
        if (positions.size() == 1) {
            if (cellAtPos(positions[0])->isBomb()) {
                auto curOpenedBombsNum = opponentPlayer.openedBombsNum();
                opponentPlayer.setOpenedBombsNum(curOpenedBombsNum + 1);
                opponentPlayer.setScore(opponentPlayer.score() + GAME_SOCRE_BOMB_OPENED);
            } else {
                auto curOpenedNotBombsNum = opponentPlayer.openedNotBombsNum();
                opponentPlayer.setOpenedNotBombsNum(curOpenedNotBombsNum + 1);
                opponentPlayer.setScore(opponentPlayer.score() + GAME_SOCRE_NOT_BOMB_OPENED);
            }
        } else {
            auto curOpenedNotBombsNum = opponentPlayer.openedNotBombsNum();
            opponentPlayer.setOpenedNotBombsNum(curOpenedNotBombsNum + positions.size());
        }
    } else {
        auto &selfPlayer = getSelfPlayer();
        if (positions.size() == 1) {
            if (cellAtPos(positions[0])->isBomb()) {
                auto curOpenedBombsNum = selfPlayer.openedBombsNum();
                selfPlayer.setOpenedBombsNum(curOpenedBombsNum + 1);
                selfPlayer.setScore(selfPlayer.score() + GAME_SOCRE_BOMB_OPENED);
            } else {
                auto curOpenedNotBombsNum = selfPlayer.openedNotBombsNum();
                selfPlayer.setOpenedNotBombsNum(curOpenedNotBombsNum + 1);
                selfPlayer.setScore(selfPlayer.score() + GAME_SOCRE_NOT_BOMB_OPENED);
            }
        } else {
            auto curOpenedNotBombsNum = selfPlayer.openedNotBombsNum();
            selfPlayer.setOpenedNotBombsNum(curOpenedNotBombsNum + positions.size());
        }
    }

    auto gameWidgetPtr = gameWidget_.lock();
    if (gameWidgetPtr == nullptr) {
        std::cout << "game widget prt is null" << std::endl;
        return;
    }

    gameWidgetPtr->refreshScoreBoard();

}

// 处理本地鼠标事件，向服务器反馈玩家鼠标点击结果
void MineSweeprWidget::mousePressEvent(QMouseEvent* event) {
    int x = event->pos().x();
    int y = event->pos().y();

    qDebug() << "x: " << x << "y: " << y;
    Position pos(y / gMineSweeperCellPixSize, x / gMineSweeperCellPixSize);

    if (event->buttons() == Qt::LeftButton) {
        qDebug() << "left button clicked";
        qDebug() << "row = " << pos.row_ << ", col = " << pos.col_;
        onLocalLeftButtonClicked(pos);
    }
    else if (event->buttons() == Qt::RightButton) {
        qDebug() << "right button clicked";
        qDebug() << "row = " << pos.row_ << ", col = " << pos.col_;
        onLocalRightButtonClicked(pos);
    } else if (event->buttons() == (Qt::LeftButton | Qt::RightButton)) {
        qDebug() << "left & right button clicked";
        qDebug() << "row = " << pos.row_ << ", col = " << pos.col_;
        onLocalLeftRightButtonClicked(pos);
    }
}

void MineSweeprWidget::setGameWidget(std::shared_ptr<GameWidget> gameWidget)
{
    gameWidget_ = gameWidget;
}
